<template>
  <div class="json-formatter module-container">
    <div class="module-header">
      <h2>JSON 格式化</h2>
      <p class="module-description">JSON 格式化、验证和压缩工具</p>
    </div>

    <div class="module-content">
      <div class="formatter-container">
        <div class="input-section">
          <div class="section-header">
            <h3>输入</h3>
            <div class="actions">
              <el-button size="small" @click="clearInput">清空</el-button>
              <el-button size="small" @click="loadSample">加载示例</el-button>
              <el-button size="small" @click="pasteFromClipboard">粘贴</el-button>
            </div>
          </div>
          <el-input
            type="textarea"
            v-model="inputJson"
            :rows="20"
            placeholder="在此输入或粘贴 JSON 数据..."
            @input="onInputChange"
          />
          <div class="status-bar" v-if="inputError">
            <el-alert
              :title="inputError"
              type="error"
              :closable="false"
              show-icon
            />
          </div>
        </div>

        <div class="control-section">
          <el-button type="primary" @click="formatJson" :disabled="!isValidJson">
            格式化 <i class="el-icon-right"></i>
          </el-button>
          <el-button @click="minifyJson" :disabled="!isValidJson">
            压缩
          </el-button>
          <el-button @click="sortKeys" :disabled="!isValidJson">
            排序键
          </el-button>
          <el-button @click="escapeJson" :disabled="!isValidJson">
            转义
          </el-button>
          <el-button @click="unescapeJson">
            反转义
          </el-button>
        </div>

        <div class="output-section">
          <div class="section-header">
            <h3>输出</h3>
            <div class="actions">
              <el-button size="small" @click="copyOutput" :disabled="!outputJson">
                复制
              </el-button>
              <el-button size="small" @click="downloadOutput" :disabled="!outputJson">
                下载
              </el-button>
              <el-button size="small" @click="clearOutput">清空</el-button>
            </div>
          </div>
          <el-input
            type="textarea"
            v-model="outputJson"
            :rows="20"
            placeholder="格式化后的 JSON 将显示在这里..."
            readonly
          />
          <div class="status-bar" v-if="outputInfo">
            <span class="info-text">{{ outputInfo }}</span>
          </div>
        </div>
      </div>

      <div class="options-panel">
        <h3>格式化选项</h3>
        <el-form label-width="120px">
          <el-form-item label="缩进">
            <el-radio-group v-model="formatOptions.indent">
              <el-radio :label="2">2 空格</el-radio>
              <el-radio :label="4">4 空格</el-radio>
              <el-radio label="tab">Tab</el-radio>
            </el-radio-group>
          </el-form-item>
          
          <el-form-item label="引号风格">
            <el-radio-group v-model="formatOptions.quoteStyle">
              <el-radio label="double">双引号</el-radio>
              <el-radio label="single">单引号</el-radio>
            </el-radio-group>
          </el-form-item>
          
          <el-form-item label="尾随逗号">
            <el-switch v-model="formatOptions.trailingComma" />
          </el-form-item>
        </el-form>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'JsonFormatter',
  data() {
    return {
      inputJson: '',
      outputJson: '',
      inputError: '',
      outputInfo: '',
      isValidJson: false,
      formatOptions: {
        indent: 2,
        quoteStyle: 'double',
        trailingComma: false
      }
    }
  },
  methods: {
    onInputChange() {
      this.validateJson()
    },
    
    validateJson() {
      if (!this.inputJson.trim()) {
        this.inputError = ''
        this.isValidJson = false
        return
      }
      
      try {
        JSON.parse(this.inputJson)
        this.inputError = ''
        this.isValidJson = true
      } catch (e) {
        this.inputError = `JSON 格式错误: ${e.message}`
        this.isValidJson = false
      }
    },
    
    formatJson() {
      try {
        const parsed = JSON.parse(this.inputJson)
        const indent = this.formatOptions.indent === 'tab' ? '\t' : this.formatOptions.indent
        this.outputJson = JSON.stringify(parsed, null, indent)
        this.updateOutputInfo()
      } catch (e) {
        this.$message.error('格式化失败: ' + e.message)
      }
    },
    
    minifyJson() {
      try {
        const parsed = JSON.parse(this.inputJson)
        this.outputJson = JSON.stringify(parsed)
        this.updateOutputInfo()
      } catch (e) {
        this.$message.error('压缩失败: ' + e.message)
      }
    },
    
    sortKeys() {
      try {
        const parsed = JSON.parse(this.inputJson)
        const sorted = this.sortObjectKeys(parsed)
        const indent = this.formatOptions.indent === 'tab' ? '\t' : this.formatOptions.indent
        this.outputJson = JSON.stringify(sorted, null, indent)
        this.updateOutputInfo()
      } catch (e) {
        this.$message.error('排序失败: ' + e.message)
      }
    },
    
    sortObjectKeys(obj) {
      if (Array.isArray(obj)) {
        return obj.map(item => this.sortObjectKeys(item))
      } else if (obj !== null && typeof obj === 'object') {
        return Object.keys(obj)
          .sort()
          .reduce((result, key) => {
            result[key] = this.sortObjectKeys(obj[key])
            return result
          }, {})
      }
      return obj
    },
    
    escapeJson() {
      try {
        const parsed = JSON.parse(this.inputJson)
        this.outputJson = JSON.stringify(JSON.stringify(parsed))
        this.updateOutputInfo()
      } catch (e) {
        this.$message.error('转义失败: ' + e.message)
      }
    },
    
    unescapeJson() {
      try {
        const unescaped = JSON.parse(this.inputJson)
        this.outputJson = typeof unescaped === 'string' ? unescaped : JSON.stringify(unescaped, null, 2)
        this.updateOutputInfo()
      } catch (e) {
        this.$message.error('反转义失败: ' + e.message)
      }
    },
    
    clearInput() {
      this.inputJson = ''
      this.inputError = ''
      this.isValidJson = false
    },
    
    clearOutput() {
      this.outputJson = ''
      this.outputInfo = ''
    },
    
    loadSample() {
      this.inputJson = JSON.stringify({
        name: 'LinkVerify',
        version: '1.0.0',
        description: 'Multi-Service Communication Debug Tool',
        features: ['HTTP', 'MQTT', 'WebSocket'],
        config: {
          timeout: 30000,
          retries: 3
        }
      }, null, 2)
      this.validateJson()
    },
    
    async pasteFromClipboard() {
      try {
        const text = await navigator.clipboard.readText()
        this.inputJson = text
        this.validateJson()
      } catch (e) {
        this.$message.error('粘贴失败')
      }
    },
    
    copyOutput() {
      navigator.clipboard.writeText(this.outputJson).then(() => {
        this.$message.success('已复制到剪贴板')
      }).catch(() => {
        this.$message.error('复制失败')
      })
    },
    
    downloadOutput() {
      const blob = new Blob([this.outputJson], { type: 'application/json' })
      const url = URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = url
      a.download = `formatted_${Date.now()}.json`
      a.click()
      URL.revokeObjectURL(url)
    },
    
    updateOutputInfo() {
      if (!this.outputJson) {
        this.outputInfo = ''
        return
      }
      
      const lines = this.outputJson.split('\n').length
      const size = new Blob([this.outputJson]).size
      const sizeStr = size < 1024 ? `${size} B` : `${(size / 1024).toFixed(2)} KB`
      
      this.outputInfo = `行数: ${lines} | 大小: ${sizeStr}`
    }
  }
}
</script>

<style lang="scss" scoped>
@import '../../styles/variables.scss';

.json-formatter {
  .module-content {
    padding: $spacing-large;
  }
  
  .formatter-container {
    display: flex;
    gap: $spacing-medium;
    margin-bottom: $spacing-large;
    
    .input-section,
    .output-section {
      flex: 1;
      display: flex;
      flex-direction: column;
      
      .section-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: $spacing-base;
        
        h3 {
          margin: 0;
        }
        
        .actions {
          display: flex;
          gap: $spacing-small;
        }
      }
      
      .status-bar {
        margin-top: $spacing-small;
        
        .info-text {
          font-size: $font-size-small;
          color: $text-secondary;
        }
      }
    }
    
    .control-section {
      display: flex;
      flex-direction: column;
      gap: $spacing-small;
      padding-top: 40px;
    }
  }
  
  .options-panel {
    background: #fff;
    border-radius: 8px;
    padding: $spacing-large;
    box-shadow: $box-shadow-light;
    
    h3 {
      margin-top: 0;
      margin-bottom: $spacing-medium;
    }
  }
}
</style>